package ift585.serveur;

import java.io.File;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;

public class Serveur {

	private static final int RECEIVE_TIMEOUT = 2000;
	private static final int MAX_RUNNING_THREAD = 10;
	private static final int PACKET_LENTGH = 1024;
	private static final int ACCEPTING_PORT = 65000;
	private static File stopFile = new File(System.getProperty("user.dir") + System.getProperty("file.separator") + "stop_file");
	
	private DatagramSocket serverSocket = null;
	private ExecutorService executor = null;
	
	public Serveur() throws SocketException {
		serverSocket = new DatagramSocket(ACCEPTING_PORT);
		serverSocket.setSoTimeout(RECEIVE_TIMEOUT);
		executor = Executors.newFixedThreadPool(MAX_RUNNING_THREAD);
	}
	
	public void startServer() {
		
		byte [] dataBuffer = new byte[PACKET_LENTGH];
		DatagramPacket dataReceived = new DatagramPacket(dataBuffer, PACKET_LENTGH);

		System.out.println("Starting file server");
		
		int threadPort = ACCEPTING_PORT + 1;
		
		while(! isRequiredToStop()){
			try {
				serverSocket.receive(dataReceived);
				
				InetAddress remoteClient = dataReceived.getAddress();
				int clientPort = dataReceived.getPort();
				byte [] messageFromClient = dataReceived.getData();
				
				System.out.println("Connection requested");
				
				executor.execute(new FileTransfertHandler(messageFromClient, remoteClient, clientPort, threadPort, PACKET_LENTGH));
				threadPort++;
				
			}
			catch (SocketTimeoutException e) {
				System.out.println("Timeout lifted on socket receive, waiting again for new client");
			}
			catch (RejectedExecutionException e) {
				System.out.println("Operation requested cannot be executed");
			}
			catch (IOException e) {
				e.printStackTrace();
			}
		}
		executor.shutdown();
	}
	
	private boolean isRequiredToStop() {
		if(stopFile.exists())
		{
			System.out.println("Server stop requested. Awaiting end of pending transmission");
			stopFile.delete();
			return true;
		}
		return false;
	}

	public static void main(String[] args) {
		try {
			Serveur oneServer = new Serveur();
			oneServer.startServer();
			
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		
		System.out.println("Server ended");
	}
}
